﻿using System.ComponentModel;
using System.ComponentModel.Design;
using System.Reflection;
using System.Windows.Forms;

namespace C4F.VistaP2P.Win.Media
{
    public class MediaDesignerActionList : DesignerActionList
    {
        /// <summary>
        /// This class enables WinForms Design Time support
        /// </summary>
        public MediaDesignerActionList(IComponent component)
            : base(component)
        {
        }

        /// <summary>
        /// The list of items to show in the smart tag on the design form.
        /// </summary>
        /// <returns></returns>
        public override DesignerActionItemCollection GetSortedActionItems()
        {

            // Create list to store designer action items
            DesignerActionItemCollection actionItems = new DesignerActionItemCollection();


            //// Add Design category header text
            actionItems.Add(new DesignerActionHeaderItem("P2P Controls"));

            // Add Design category descriptive label
            actionItems.Add(
              new DesignerActionTextItem(
                "Properties that affect which control the Media Control uses.",
                "Design"));

            // Dock/Undock designer action method item
            actionItems.Add(
              new DesignerActionMethodItem(
                this,
                "ToggleDockStyle",
                GetDockStyleText(),
                "Design",
                "Dock or undock this control in it's parent container.",
                true));

            actionItems.Add(
               new DesignerActionPropertyItem(
                 "Visible",
                 "Visible",
                 GetCategory(MediaControl, "Visible"),
                 GetDescription(MediaControl, "Visible")));  
       
            actionItems.Add(
              new DesignerActionPropertyItem(
                "StatusLog",
                "Status Log",
                GetCategory(this.MediaControl, "StatusLog"),
                GetDescription(this.MediaControl, "StatusLog")));

            actionItems.Add(
              new DesignerActionPropertyItem(
                "SendButton",
                "Send File Button",
                GetCategory(this.MediaControl, "SendButton"),
                GetDescription(this.MediaControl, "SendButton")));
            
            actionItems.Add(
             new DesignerActionPropertyItem(
               "MediaPlayer",
               "Media Player",
               GetCategory(this.MediaControl, "MediaPlayer"),
               GetDescription(this.MediaControl, "MediaPlayer")));

            // Return action list to design time item
            return actionItems;
        }


        /// <summary>
        /// The Status log control to hook up if they select it
        /// </summary>
        public TextBox StatusLog
        {
            get { return this.MediaControl.StatusLog; }
            set { SetProperty("StatusLog", value); }
        }

        /// <summary>
        /// The Send Button control to hook up if they select it
        /// </summary>
        public Button SendButton
        {
            get { return this.MediaControl.SendButton; }
            set { SetProperty("SendButton", value); }
        }

        /// <summary>
        /// The Media Player control to hook up if they select it
        /// </summary>
        public AxWMPLib.AxWindowsMediaPlayer MediaPlayer
        {
            get { return this.MediaControl.MediaPlayer; }
            set { SetProperty("MediaPlayer", value); }
        }

        /// <summary>
        /// Set the control visible or invisible
        /// </summary>
        public bool Visible
        {
            get { return this.MediaControl.ShadowVisible; }
            set { SetProperty("ShadowVisible", value); }
        }

        /// <summary>
        /// Toggle the Dock style of this control
        /// </summary>
        public void ToggleDockStyle()
        {            
            if (this.MediaControl.Dock != DockStyle.Fill)
            {
                SetProperty("Dock", DockStyle.Fill);
            }
            else
            {
                SetProperty("Dock", DockStyle.None);
            }
        }

        /// <summary>
        /// Helper method that returns an appropriate
        /// display name for the Dock/Undock property,
        /// depending on the current dock property value
        /// </summary>
        /// <returns></returns>
        private string GetDockStyleText()
        {
            if (this.MediaControl.Dock == DockStyle.Fill)
            {
                return "Undock in parent container";
            }
            else
            {
                return "Dock in parent container";
            }
        }

        
        /// <summary>
        /// Helper property to acquire a MediaControl reference
        /// </summary>
        private MediaControl MediaControl
        {
            get { return (MediaControl)this.Component; }
        }

        
        /// <summary>
        /// Helper method to safely set a component’s property
        /// </summary>
        /// <param name="propertyName">The property to set</param>
        /// <param name="value">the value to set the property to</param>
        private void SetProperty(string propertyName, object value)
        {
            // Get property
            PropertyDescriptor property = TypeDescriptor.GetProperties(this.MediaControl)[propertyName];
            // Set property value
            property.SetValue(this.MediaControl, value);
        }

        /// <summary>
        /// Helper method to return the Category string from a
        /// CategoryAttribute assigned to a property exposed by 
        /// the specified object
        /// </summary>
        /// <param name="source">The control to get the category from</param>
        /// <param name="propertyName">the property to get the category string from</param>
        /// <returns>the category</returns>
        private static string GetCategory(object source, string propertyName)
        {
            PropertyInfo property = source.GetType().GetProperty(propertyName);
            CategoryAttribute attribute = (CategoryAttribute)property.GetCustomAttributes(typeof(CategoryAttribute), false)[0];
            if (attribute == null) return null;
            return attribute.Category;
        }

        /// <summary>
        /// Helper method to return the Description string from a
        /// DescriptionAttribute assigned to a property exposed by 
        /// the specified object
        /// </summary>
        /// <param name="source">The control to get the property from</param>
        /// <param name="propertyName">the property to get the description from</param>
        /// <returns>the description of the property</returns>
        private static string GetDescription(object source, string propertyName)
        {
            PropertyInfo property = source.GetType().GetProperty(propertyName);
            DescriptionAttribute attribute = (DescriptionAttribute)property.GetCustomAttributes(typeof(DescriptionAttribute), false)[0];
            if (attribute == null) return null;
            return attribute.Description;
        }
    }
}
